/**********************************************************************
 *
 * This code is developed for the course Informatica Industrial II
 * of Universidad Carlos III de Madrid - 2012
 * Authors: Victor González-Pacheco, Alberto Valero-Gomez
 *
 * The code is licenced under the Common Creative License,
 * Attribution-ShareAlike 3.0
 *
 * You are free:
 *   - to Share - to copy, distribute and transmit the work
 *   - to Remix - to adapt the work
 *
 * Under the following conditions:
 *   - Attribution. You must attribute the work in the manner specified
 *     by the author or licensor (but not in any way that suggests that
 *     they endorse you or your use of the work).
 *   - Share Alike. If you alter, transform, or build upon this work,
 *     you may distribute the resulting work only under the same or
 *     similar license to this one.
 *
 * Any of the above conditions can be waived if you get permission
 * from the copyright holder.  Nothing in this license impairs or
 * restricts the author's moral rights.
 *
 * It is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.
 **********************************************************************/


#ifndef UDPSOCKET__H
#define UDPSOCKET__H

#include "AbstractSocket.h"
#include <cstdio>
#include <cerrno>
#include <stdio.h>
#include <cstring>


/**
  * \brief UDP Socket Class
  * This class implements an Abstract TCP Socket Class using the paradigm of streams
  */
class UDPSocket : public AbstractSocket{
    friend class TCPSocketClient;
    friend class TCPSocketServer;

public:

    /**
      * \brief Parametrized Constructor.
      */
    UDPSocket(string rem_ip, int rem_port, string local_ip, int local_port) throw(string);
    UDPSocket(int fd);

    /**
     * @brief Default TCPSocket copy constructor
     * @param other TCPSocket to be copied
     */
    UDPSocket(const UDPSocket & other):
        AbstractSocket(other._ip,
                       other._port,
                       other._local_ip,
                       other._local_port,
                       other._socket_fd)
    { }

    /**
     * @brief operator =
     * Assignation operator. Required to use std::vector
     * @param other Other TCPSocket
     * @return TCPSocket
     */
    UDPSocket & operator = (const UDPSocket& other){
        _ip = other._ip;
        _port = other._port;
        _local_ip = other._local_ip;
        _local_port = other._local_port;
        _socket_fd = other._socket_fd;

        return *this;
    }


    /**
      * \brief writes a string though the socket connection
      * << Function to send a string though the socket connection
      * \param cad string to send
      * \param trials The number of times it tries to send the string before dimissing
      * \return If it succeeds, the function returns the number of bytes, otherwise returns -1
      */
    virtual int write (const string & cad, int trials=1) const throw (char const *);

    /**
      * \brief Reads the incoming data from a socket
      * Reads the Incoming data from a socket
      * \throw String exception when reading is not successful
      * \relates int write (const string & cad, int trials=1);
      * \return the read string
      */
    virtual string read() const throw(char const *);

protected:

    /**
      * \brief Opens a Socket
      * Opens a Socket
      * \throw string if socket cannot be opened
      * \return the file descriptor of the socket
      */
    virtual int open() throw(char const *);
};

#endif //TCPSOCKET__H
